package main.labtwo;

import static java.lang.Math.pow;

/**
 * Created with IntelliJ IDEA.
 * User: Борис
 * Date: 28.11.13
 * Time: 15:34
 * To change this template use File | Settings | File Templates.
 */
public class Determinant {

    static double determinantMatrixSizeFour(double[][] matrix){
        double minor;
        double det = 0;
        for(int i = 0; i<4; i++){
            minor = determinantSizeThree(getMinorMatrix(matrix,0,i));
            det += pow(-1,i)*matrix[0][i]*minor;
        }
        return det;
    }

    static private double[][] getMinorMatrix(double[][] matrix,int i1, int j1){
        int size = matrix.length;
        double[][] copyMOfSystem = new double[size][size]; // копия матрицы системы
        for(int i = 0; i<size; i++){
            for(int j = 0; j<size; j++){
                copyMOfSystem[i][j] = matrix[i][j];
            }
        }
        for(int i = i1; i<size-1; i++)
            for(int j = 0; j<size; j++){
                copyMOfSystem[i][j] = copyMOfSystem[i+1][j];
            }
        double[][] matrixA = new double[size-1][size]; // вспомогательная матрица

        for(int i = 0; i<size-1; i++)
            for(int j = 0; j<size; j++){
                matrixA[i][j] = copyMOfSystem[i][j];
            }

        for(int i = 0; i<matrixA.length; i++)
            for(int j = j1; j<size-1; j++){
                matrixA[i][j] = matrixA[i][j+1];
            }

        double[][] minor = new double[size-1][size-1];
        for(int i = 0; i<minor.length; i++)
            for(int j = 0; j<minor.length; j++){
                minor[i][j] = matrixA[i][j];
            }

        return minor;
    }


    // метод вычисляет определитель матрицы 2х2
    static private double determinantSizeTwo(double[][] matrix){
        return matrix[0][0]*matrix[1][1]-matrix[1][0]*matrix[0][1];
    }
    // метод вычисляет определитель матрицы 3х3
    static private double determinantSizeThree(double[][] matrix){
        double[][] matrixTwoByTwoLeft, matrixTwoByTwoCenter, matrixTwoByTwoRight;
        matrixTwoByTwoLeft = getTwoByTwoMatrixLeft(matrix);
        matrixTwoByTwoCenter = getTwoByTwoMatrixCenter(matrix);
        matrixTwoByTwoRight = getTwoByTwoMatrixRight(matrix);
        return matrix[0][0]*determinantSizeTwo(matrixTwoByTwoLeft)-matrix[0][1]*determinantSizeTwo(matrixTwoByTwoCenter)+matrix[0][2]*determinantSizeTwo(matrixTwoByTwoRight);
    }
    /*
     метод возвращает матрицу 2x2, когда вычеркнут левый столбец
     matrix[] - матрица 3х3
     */
    static private double[][] getTwoByTwoMatrixLeft(double[][] matrix){
        double[][] matrixTwoByTwo = new double[2][2];
        matrixTwoByTwo[0][0] = matrix[1][1];
        matrixTwoByTwo[0][1] = matrix[1][2];
        matrixTwoByTwo[1][0] = matrix[2][1];
        matrixTwoByTwo[1][1] = matrix[2][2];
        return matrixTwoByTwo;
    }
    /*
     метод возвращает матрицу 2x2, когда вычеркнут центральный столбец
     matrix[] - матрица 3х3
     */
    static private double[][] getTwoByTwoMatrixCenter(double[][] matrix){
        double[][] matrixTwoByTwo = new double[2][2];
        matrixTwoByTwo[0][0] = matrix[1][0];
        matrixTwoByTwo[0][1] = matrix[1][2];
        matrixTwoByTwo[1][0] = matrix[2][0];
        matrixTwoByTwo[1][1] = matrix[2][2];
        return matrixTwoByTwo;
    }
    /*
     метод возвращает матрицу 2x2, когда вычеркнут правый столбец
     matrix[] - матрица 3х3
     */
    static private double[][] getTwoByTwoMatrixRight(double[][] matrix){
        double[][] matrixTwoByTwo = new double[2][2];
        matrixTwoByTwo[0][0] = matrix[1][0];
        matrixTwoByTwo[0][1] = matrix[1][1];
        matrixTwoByTwo[1][0] = matrix[2][0];
        matrixTwoByTwo[1][1] = matrix[2][1];
        return matrixTwoByTwo;
    }
}
